Skip to content

Refactor remote WebSocket transport and add servlet adapter#105

Draft
kamikaz1k wants to merge 6 commits into
agentclientprotocol:masterfrom
kamikaz1k:codex/remote-transport-architecture
Draft

Refactor remote WebSocket transport and add servlet adapter#105
kamikaz1k wants to merge 6 commits into
agentclientprotocol:masterfrom
kamikaz1k:codex/remote-transport-architecture

Conversation

@kamikaz1k

@kamikaz1k kamikaz1k commented Jul 5, 2026

Copy link
Copy Markdown

AI Disclosure: this PR was written with the help of Codex

Summary

  • refactor WebSocket JSON-RPC framing into a framework-neutral RemoteWebSocketTransport
  • keep the existing Ktor WebSocketTransport API as a compatibility wrapper
  • add a Javax Servlet/JSR-356 WebSocket server adapter with lifecycle and protocol-level tests (used ktor coverage as baseline)
  • document the extension architecture and staged transport plan (can remove from PR)

Consumer API

fun connectAcp(
    container: WebSocketContainer,
    scope: CoroutineScope,
): Client {
    val protocol = container.acpProtocolOnClientWebSocket(
        uri = URI.create("ws://localhost:8080/acp"),
        parentScope = scope,
        protocolOptions = ProtocolOptions(protocolDebugName = "servlet client")
    )

    protocol.start()
    return Client(protocol)
}
fun ServletContext.registerAcpAgent(
    scope: CoroutineScope,
    agentSupport: AgentSupport,
) {
    acpProtocolOnServerWebSocket(
        path = "/acp",
        parentScope = scope,
        protocolOptions = ProtocolOptions(protocolDebugName = "servlet agent")
    ) { protocol: Protocol ->
        Agent(protocol, agentSupport)
        protocol.start()
    }
}

Motivation / Background

My company doesn't use ktor so I wanted to see if I could support servlets without introducing any breaking changes.

Also, in preparation of the HTTP SSE RFC, I also tried to align the refactor toward transport agnosticity. The intended design is captured in ARCHITECTURE.md (along with the PLAN.md) so please let me know if this direction makes sense.

Target Architecture

flowchart TB
    App["Host application"]
    KtorClient["acp-ktor-client"]
    KtorServer["acp-ktor-server"]
    KtorShared["acp-ktor"]
    ServletClient["acp-servlet-client"]
    ServletServer["acp-servlet-server"]
    Future["Future framework adapter"]
    Endpoint["Remote /acp endpoint adapter"]
    WS["WebSocket profile"]
    HTTP["Streamable HTTP/SSE profile"]
    Remote["Generic remote transport core"]
    T["Transport interface"]
    P["ACP protocol runtime"]
    M["ACP model and JSON-RPC types"]

    App --> KtorClient
    App --> KtorServer
    App --> ServletClient
    App --> ServletServer
    App --> Future

    KtorClient --> KtorShared
    KtorServer --> KtorShared
    KtorShared --> Endpoint
    ServletClient --> Endpoint
    ServletServer --> Endpoint
    Future --> Endpoint

    Endpoint --> WS
    Endpoint --> HTTP
    WS --> Remote
    HTTP --> Remote
    Remote --> T
    T --> P
    P --> M
Loading

Validation

  • ./gradlew :acp:jvmTest :acp-servlet-server:test :acp-servlet-server:apiCheck
  • ./gradlew check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant